﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;

namespace Jewelnoid
{
    class TetrisPiece
    {
        static public int maxMatrixSize = 4;
        static public Dictionary<Color, Type> colorTypeMap = new Dictionary<Color, Type>
                {
	                {Color.Blue, Type.SMirror},
	                {Color.Yellow, Type.L},
	                {Color.Red, Type.S},
	                {Color.Green, Type.Square},
	                {Color.Purple, Type.T},
	                {Color.Orange, Type.LMirror},
	                {Color.White, Type.Bar}
                };

        static public Dictionary<Type, Color> typeColorMap = new Dictionary<Type, Color>
                {
	                {Type.SMirror, Color.Blue},
	                {Type.L, Color.Yellow},
	                {Type.S, Color.Red},
	                {Type.Square, Color.Green},
	                {Type.T, Color.Purple},
	                {Type.LMirror, Color.Orange},
	                {Type.Bar, Color.White}
                };

        public enum Type { Bar, S, SMirror, L, LMirror, T, Square };
        public Type type;
        public List<List<int>> matrix;
        public Color color;


        public TetrisPiece(List<List<int>> matrix, Type type, Color color)
        {
            this.matrix = matrix;
            this.type = type;
            this.color = color;
        }

        public void rotate()
        {
            switch (this.type)
            {
                case Type.Bar:
                    rotateBar(this.matrix);
                    break;
                case Type.S:
                    rotateS(this.matrix);
                    break;
                case Type.SMirror:
                    rotateSMirror(this.matrix);
                    break;
                case Type.L:
                    rotateL(this.matrix);
                    break;
                case Type.LMirror:
                    rotateLMirror(this.matrix);
                    break;
                case Type.T:
                    rotateT(this.matrix);
                    break;
            }
        }

        static public TetrisPiece generatePiece(Type type)
        {
            List<List<int>> pieceMatrix = new List<List<int>>();
            int colorNumber = 0;

            for (int i = 0; i < maxMatrixSize; i++) //Cria uma matriz 4x4 com todos os valores 0 (para ficar mais facil de visualizar a posição da peça.
            {
                List<int> line = new List<int>();

                for (int j = 0; j < maxMatrixSize; j++)
                {
                    line.Add(0);
                }

                pieceMatrix.Add(line);
            }

            switch (type)
            {
                case Type.SMirror: // Azul
                    colorNumber = Block.colorNumberMap[typeColorMap[Type.SMirror]];
                    pieceMatrix[2][0] = colorNumber;
                    pieceMatrix[2][1] = colorNumber;
                    pieceMatrix[3][1] = colorNumber;
                    pieceMatrix[3][2] = colorNumber;
                    break;

                case Type.L: // Amarelo
                    colorNumber = Block.colorNumberMap[typeColorMap[Type.L]];
                    pieceMatrix[2][2] = colorNumber;
                    pieceMatrix[3][0] = colorNumber;
                    pieceMatrix[3][1] = colorNumber;
                    pieceMatrix[3][2] = colorNumber;
                    break;

                case Type.S:  //Vermelho
                    colorNumber = Block.colorNumberMap[typeColorMap[Type.S]];
                    pieceMatrix[2][1] = colorNumber;
                    pieceMatrix[2][2] = colorNumber;
                    pieceMatrix[3][0] = colorNumber;
                    pieceMatrix[3][1] = colorNumber;
                    break;

                case Type.Square: //Verde
                    colorNumber = Block.colorNumberMap[typeColorMap[Type.Square]];
                    pieceMatrix[2][0] = colorNumber;
                    pieceMatrix[2][1] = colorNumber;
                    pieceMatrix[3][0] = colorNumber;
                    pieceMatrix[3][1] = colorNumber;
                    break;

                case Type.T: //Roxo
                    colorNumber = Block.colorNumberMap[typeColorMap[Type.T]];
                    pieceMatrix[2][1] = colorNumber;
                    pieceMatrix[3][0] = colorNumber;
                    pieceMatrix[3][1] = colorNumber;
                    pieceMatrix[3][2] = colorNumber;
                    break;

                case Type.LMirror: //Laranja
                    colorNumber = Block.colorNumberMap[typeColorMap[Type.LMirror]];
                    pieceMatrix[2][0] = colorNumber;
                    pieceMatrix[3][0] = colorNumber;
                    pieceMatrix[3][1] = colorNumber;
                    pieceMatrix[3][2] = colorNumber;
                    break;

                case Type.Bar: //White
                    colorNumber = Block.colorNumberMap[typeColorMap[Type.Bar]];
                    pieceMatrix[3][0] = colorNumber;
                    pieceMatrix[3][1] = colorNumber;
                    pieceMatrix[3][2] = colorNumber;
                    pieceMatrix[3][3] = colorNumber;
                    break;
            }

            return new TetrisPiece(pieceMatrix, type, typeColorMap[type]);
        }

        /// <summary>
        ///     Gera uma peça de tetris genérica. 
        ///     As peças de tetris estão mapeadas como uma matriz 4x4 de inteiros, seguindo o mapeamento dos blocos do projeto.
        /// </summary>
        /// <returns>A matriz 4x4 da peça. 0 onde não tem nada, e um número (referente a cor) onde tem</returns>
        static public TetrisPiece generateGenericPiece(int seed)
        {
            Random rad = new Random();
            Random random = new Random(seed * rad.Next());
            Color genericColor = Level.genericColor(random.Next(100));

            return generatePiece(colorTypeMap[genericColor]);
        }

        //Apenas para teste
        static public void printMatrix(List<List<int>> tetrisPieceMatrix)
        {
            String line;

            Console.Write("\n\nMatrix:\n");

            for (int i = 0; i < tetrisPieceMatrix.Count; i++)
            {
                line = "| ";

                for (int j = 0; j < tetrisPieceMatrix[i].Count; j++)
                {
                    line = String.Concat(line, tetrisPieceMatrix[i][j]);
                }

                line = String.Concat(line, " |\n");
                Console.Write(line);
            }
        }

        private void rotateBar(List<List<int>> barMatrix)
        {
            if (barMatrix[0][0] != 0)
            {
                barMatrix[0][0] = 0;
                barMatrix[1][0] = 0;
                barMatrix[2][0] = 0;
                barMatrix[3][1] = 7;
                barMatrix[3][2] = 7;
                barMatrix[3][3] = 7;
            }
            else
            {
                barMatrix[0][0] = 7;
                barMatrix[1][0] = 7;
                barMatrix[2][0] = 7;
                barMatrix[3][1] = 0;
                barMatrix[3][2] = 0;
                barMatrix[3][3] = 0;
            }
        }

        private void rotateS(List<List<int>> sMatrix)
        {
            if (sMatrix[1][0] != 0)
            {
                sMatrix[1][0] = 0;
                sMatrix[2][0] = 0;
                sMatrix[2][2] = 3;
                sMatrix[3][0] = 3;
            }
            else
            {
                sMatrix[1][0] = 3;
                sMatrix[2][0] = 3;
                sMatrix[2][2] = 0;
                sMatrix[3][0] = 0;
            }
        }

        private void rotateSMirror(List<List<int>> sMirrorMatrix)
        {
            if (sMirrorMatrix[3][0] != 0)
            {
                sMirrorMatrix[1][1] = 0;
                sMirrorMatrix[3][0] = 0;
                sMirrorMatrix[3][1] = 1;
                sMirrorMatrix[3][2] = 1;
            }
            else
            {
                sMirrorMatrix[1][1] = 1;
                sMirrorMatrix[3][0] = 1;
                sMirrorMatrix[3][1] = 0;
                sMirrorMatrix[3][2] = 0;
            }
        }

        private void rotateL(List<List<int>> lMatrix)
        {
            if (lMatrix[1][1] != 0)  //Posição L de cabeça pra baixo
            {
                lMatrix[1][0] = 0;
                lMatrix[1][1] = 0;
                lMatrix[2][0] = 2;
                lMatrix[2][2] = 2;
                lMatrix[3][0] = 2;
                lMatrix[3][1] = 0;
            }
            else if (lMatrix[2][2] != 0 && lMatrix[3][2] == 0) //Posição L deitado seguindo rotação do de cima, os demais também seguem
            {
                lMatrix[1][0] = 2;
                lMatrix[2][1] = 0;
                lMatrix[2][2] = 0;
                lMatrix[3][1] = 2;
            }
            else if (lMatrix[1][0] != 0 && lMatrix[1][1] == 0)  // L
            {
                lMatrix[1][0] = 0;
                lMatrix[2][0] = 0;
                lMatrix[2][2] = 2;
                lMatrix[3][2] = 2;
            }
            else if (lMatrix[3][2] != 0)
            {
                lMatrix[1][0] = 2;
                lMatrix[1][1] = 2;
                lMatrix[2][1] = 2;
                lMatrix[2][2] = 0;
                lMatrix[3][0] = 0;
                lMatrix[3][2] = 0;
            }
        }

        private void rotateLMirror(List<List<int>> lMirrorMatrix)
        {
            if (lMirrorMatrix[1][0] != 0)  //Posição LMirror de cabeça pra baixo
            {
                lMirrorMatrix[1][0] = 0;
                lMirrorMatrix[1][1] = 0;
                lMirrorMatrix[3][1] = 6;
                lMirrorMatrix[3][2] = 6;
            }
            else if (lMirrorMatrix[3][2] != 0 && lMirrorMatrix[2][2] == 0) //Posição LMirror deitado seguindo rotação do de cima, os demais também seguem
            {
                lMirrorMatrix[1][1] = 6;
                lMirrorMatrix[2][0] = 0;
                lMirrorMatrix[2][1] = 6;
                lMirrorMatrix[3][2] = 0;
            }
            else if (lMirrorMatrix[1][1] != 0 && lMirrorMatrix[1][0] == 0)  // LMirror
            {
                lMirrorMatrix[1][1] = 0;
                lMirrorMatrix[2][0] = 6;
                lMirrorMatrix[2][2] = 6;
                lMirrorMatrix[3][0] = 0;
                lMirrorMatrix[3][1] = 0;
                lMirrorMatrix[3][2] = 6;
            }
            else if (lMirrorMatrix[2][2] != 0)
            {
                lMirrorMatrix[1][0] = 6;
                lMirrorMatrix[1][1] = 6;
                lMirrorMatrix[2][1] = 0;
                lMirrorMatrix[2][2] = 0;
                lMirrorMatrix[3][0] = 6;
                lMirrorMatrix[3][2] = 0;
            }
        }

        private void rotateT(List<List<int>> tMatrix)
        {
            if (tMatrix[1][0] != 0)  //Posição T caido pra esquerda
            {
                tMatrix[1][0] = 0;
                tMatrix[2][0] = 0;
                tMatrix[3][1] = 5;
                tMatrix[3][2] = 5;
            }
            else if (tMatrix[3][2] != 0) //Posição T de cabeça pra baixo
            {
                tMatrix[1][1] = 5;
                tMatrix[2][0] = 5;
                tMatrix[3][0] = 0;
                tMatrix[3][2] = 0;
            }
            else if (tMatrix[1][1] != 0)  //Posição T caido pra direita
            {
                tMatrix[1][1] = 0;
                tMatrix[2][2] = 5;
            }
            else if (tMatrix[2][2] != 0)  // T
            {
                tMatrix[1][0] = 5;
                tMatrix[2][2] = 0;
                tMatrix[3][0] = 5;
                tMatrix[3][1] = 0;
            }
        }
    }
}
